"""
Redis工具类 - 用于管理token黑名单和缓存
作者：资深Flask讲师
功能：
  1. 添加token到黑名单
  2. 检查token是否在黑名单中
  3. 通用缓存操作
"""

import redis
from flask import current_app


class RedisUtil:
    """Redis工具类"""
    
    _redis_client = None
    
    @classmethod
    def get_client(cls):
        """获取Redis连接客户端（单例模式）"""
        if cls._redis_client is None:
            try:
                cls._redis_client = redis.Redis(
                    host=current_app.config.get('REDIS_HOST', 'localhost'),
                    port=current_app.config.get('REDIS_PORT', 6379),
                    db=current_app.config.get('REDIS_DB', 0),
                    password=current_app.config.get('REDIS_PASSWORD', None),
                    decode_responses=True  # 自动解码为字符串
                )
                # 测试连接
                cls._redis_client.ping()
            except Exception as e:
                print(f"Redis连接失败: {str(e)}")
                # 如果Redis连接失败，返回None，业务逻辑中需要处理
                cls._redis_client = None
        
        return cls._redis_client
    
    @classmethod
    def add_to_blacklist(cls, token, expire_seconds=3600):
        """
        将token添加到黑名单
        
        参数:
            token: str - JWT token
            expire_seconds: int - 过期时间（秒），默认1小时
        
        返回:
            bool - 是否添加成功
        """
        try:
            client = cls.get_client()
            if client is None:
                print("警告: Redis不可用，无法添加黑名单")
                return False
            
            # 使用token的哈希值作为key，减少存储空间
            key = f"blacklist:{token}"
            client.setex(key, expire_seconds, "1")
            return True
            
        except Exception as e:
            print(f"添加黑名单失败: {str(e)}")
            return False
    
    @classmethod
    def is_in_blacklist(cls, token):
        """
        检查token是否在黑名单中
        
        参数:
            token: str - JWT token
        
        返回:
            bool - 是否在黑名单中
        """
        try:
            client = cls.get_client()
            if client is None:
                # Redis不可用时，为了安全起见，不拦截请求
                # 可以根据实际需求调整策略
                return False
            
            key = f"blacklist:{token}"
            return client.exists(key) > 0
            
        except Exception as e:
            print(f"检查黑名单失败: {str(e)}")
            return False
    
    @classmethod
    def set_value(cls, key, value, expire_seconds=None):
        """
        设置缓存值
        
        参数:
            key: str - 键
            value: str - 值
            expire_seconds: int - 过期时间（秒），None表示永不过期
        """
        try:
            client = cls.get_client()
            if client is None:
                return False
            
            if expire_seconds:
                client.setex(key, expire_seconds, value)
            else:
                client.set(key, value)
            return True
            
        except Exception as e:
            print(f"设置缓存失败: {str(e)}")
            return False
    
    @classmethod
    def get_value(cls, key):
        """
        获取缓存值
        
        参数:
            key: str - 键
        
        返回:
            str - 值，不存在返回None
        """
        try:
            client = cls.get_client()
            if client is None:
                return None
            
            return client.get(key)
            
        except Exception as e:
            print(f"获取缓存失败: {str(e)}")
            return None
    
    @classmethod
    def delete_value(cls, key):
        """
        删除缓存值
        
        参数:
            key: str - 键
        
        返回:
            bool - 是否删除成功
        """
        try:
            client = cls.get_client()
            if client is None:
                return False
            
            client.delete(key)
            return True
            
        except Exception as e:
            print(f"删除缓存失败: {str(e)}")
            return False


